package features.advance.leetcode.math.easy;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author LIN
 * @date 2022-06-04 22:19
 *
 *  202. 快乐数
 *
 *  难度：简单
 *
 * 编写一个算法来判断一个数 n 是不是快乐数。
 *
 * 「快乐数」 定义为：
 *
 * 对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和。
 * 然后重复这个过程直到这个数变为 1，也可能是 无限循环 但始终变不到 1。
 * 如果这个过程 结果为 1，那么这个数就是快乐数。
 * 如果 n 是 快乐数 就返回 true ；不是，则返回 false 。
 *
 *
 *
 * 示例 1：
 *
 * 输入：n = 19
 * 输出：true
 * 解释：
 * 12 + 92 = 82
 * 82 + 22 = 68
 * 62 + 82 = 100
 * 12 + 02 + 02 = 1
 * 示例 2：
 *
 * 输入：n = 2
 * 输出：false
 *
 *
 * 提示：
 *
 * 1 <= n <= 231 - 1
 */
public class Solution202 {

    public static void main(String[] args) {
        Solution solution = new Solution() {
            @Override
            public boolean isHappy(int n) {
                // 判断是否产生了循环
                // 优化快慢指针
                Set<Integer> seen = new HashSet<>(16);
                while (!seen.contains(n) && n != 1) {
                    seen.add(n);
                    n = getSum(n);
                }
                return n == 1;
            }
            public int getSum(int n){
                int sum = 0;
                while(n > 0){
                    int a = n % 10;
                    n = n/10;
                    sum+=a*a;
                }
                return sum;
            }

        };
        boolean happy = solution.isHappy(9999);
        System.out.println(happy);


    }

    abstract static class Solution {
        private static Set<Integer> cycleMembers =
                new HashSet<>(Arrays.asList(4, 16, 37, 58, 89, 145, 42, 20));

        public int getNext(int n) {
            int totalSum = 0;
            while (n > 0) {
                int d = n % 10;
                n = n / 10;
                totalSum += d * d;
            }
            return totalSum;
        }


        public boolean isHappy(int n) {
            while (n != 1 && !cycleMembers.contains(n)) {
                n = getNext(n);
            }
            return n == 1;
        }

    }
}
